﻿using System;
using System.Runtime.CompilerServices;

namespace Hsenl {
    [FrameworkMember]
    public static class PublicEvents {
        [OnEventSystemInitialized, Order(-1000)]
        private static void Init() {
            Unload();
        }
        
        [OnEventSystemUnload]
        private static void Unload() {
            OnEntityCreatedEvent = null;
            OnEntityInstantiateEvent = null;
            OnEntityInstantiatedEvent = null;
            OnComponentAddedEvent = null;
            OnComponentRemovedEvent = null;
            OnBeforeParentChangeEvent = null;
            OnParentChangedEvent = null;
            OnEntityActivedEvent = null;
            OnEntityInactivedEvent = null;
            OnEntityDestroyedEvent = null;
            OnComponentEnabledEvent = null;
            OnComponentDisabledEvent = null;
            OnComponentDestroyedEvent = null;
        }

        public static event Action<Entity> OnEntityCreatedEvent;
        public static event Action<Entity> OnEntityInstantiateEvent;
        public static event Action<Entity> OnEntityInstantiatedEvent;
        public static event Action<Entity, Component> OnComponentAddedEvent;
        public static event Action<Entity, Component> OnComponentRemovedEvent;
        public static event Action<Entity, Entity, Entity, int> OnBeforeParentChangeEvent;
        public static event Action<Entity, Entity, Entity, int> OnParentChangedEvent;
        public static event Action<Entity> OnEntityActivedEvent;
        public static event Action<Entity> OnEntityInactivedEvent;
        public static event Action<Entity> OnEntityDestroyedEvent;
        public static event Action<Component> OnComponentEnabledEvent;
        public static event Action<Component> OnComponentDisabledEvent;
        public static event Action<Component> OnComponentDestroyedEvent;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityCreated(Entity entity) {
            try {
                OnEntityCreatedEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityInstantiate(Entity entity) {
            try {
                OnEntityInstantiateEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityInstantiated(Entity entity) {
            try {
                OnEntityInstantiatedEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnComponentAdded(Entity entity, Component component) {
            try {
                OnComponentAddedEvent?.Invoke(entity, component);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnComponentRemoved(Entity entity, Component component) {
            try {
                OnComponentRemovedEvent?.Invoke(entity, component);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnBeforeParentChange(Entity entity, Entity now, Entity futrue, int layer) {
            try {
                OnBeforeParentChangeEvent?.Invoke(entity, now, futrue, layer);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnParentChanged(Entity entity, Entity prev, Entity now, int layer) {
            try {
                OnParentChangedEvent?.Invoke(entity, prev, now, layer);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityActived(Entity entity) {
            try {
                OnEntityActivedEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityInactived(Entity entity) {
            try {
                OnEntityInactivedEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnEntityDestroyed(Entity entity) {
            try {
                OnEntityDestroyedEvent?.Invoke(entity);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        // 后于 component 触发
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnComponentEnabled(Component component) {
            try {
                OnComponentEnabledEvent?.Invoke(component);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }

        // 后于 component 触发
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnComponentDisabled(Component component) {
            try {
                OnComponentDisabledEvent?.Invoke(component);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }
        
        // 后于 component 触发
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static void OnComponentDestroyed(Component component) {
            try {
                OnComponentDestroyedEvent?.Invoke(component);
            }
            catch (Exception e) {
                Log.Error(e);
            }
        }
    }
}